package com.ych.auth;


import com.ych.modules.base.dbEntity.TUserInfoEntity;
import com.ych.modules.base.dbEntity.TUserTokenEntity;
import com.ych.modules.base.service.ITUserInfoService;
import com.ych.modules.base.service.ITUserTokenService;
import com.ych.shareEntity.ShareUserEntity;
import com.ych.utils.TLMap;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * Author: Usopp.tsui
 * Date: 2020/12/5
 * Time: 14:57
 * Description:
 */
@Component
public class AuthRealm extends AuthorizingRealm {
    @Autowired
    private ITUserInfoService  itUserInfoService;
    @Autowired
    private ITUserTokenService itUserTokenService;

    //授权（验证权限时调用）
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        ShareUserEntity<TUserTokenEntity, TUserInfoEntity> shareUserEntity = (ShareUserEntity) principalCollection.getPrimaryPrincipal();
        if (null == shareUserEntity) {
            throw new LockedAccountException("当前用户权限过期，请重新登录！");
        }
        //token时间校验
        TUserTokenEntity tokenEntity = shareUserEntity.getT();
        this.verifiedToken(tokenEntity);
        //用户账号校验
        TUserInfoEntity userEntity = shareUserEntity.getU();
        this.verifiedUser(userEntity);
        //将授权的permission名称集合赋予给shiro
        Set<String> permsSet = shareUserEntity.getPermsSet();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permsSet);
        TLMap.setToken(tokenEntity.getToken());
        TLMap.setUserId(userEntity.getUserId());
        TLMap.setMobile(userEntity.getMobile());
        return info;
    }

    //认证登录(登录时调用)
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        String accessToken = String.valueOf(usernamePasswordToken.getPassword());
        TUserTokenEntity tokenEntity = itUserTokenService.queryByToken(accessToken);
        //token校验
        this.verifiedToken(tokenEntity);
        TUserInfoEntity userInfoEntity = itUserInfoService.queryByUserId(tokenEntity.getUserId());
        //用户状态校验
        this.verifiedUser(userInfoEntity);
        //获取该用户权限列表
        Set<String> permsSet = userInfoEntity.getPermSet();
        //将当前用户,票据,权限,企业源全部封入map中进行共享
        ShareUserEntity<TUserTokenEntity, TUserInfoEntity> shareUserEntity = new ShareUserEntity();
        shareUserEntity.setT(tokenEntity);
        shareUserEntity.setU(userInfoEntity);
        shareUserEntity.setPermsSet(permsSet);
        TLMap.setToken(tokenEntity.getToken());
        TLMap.setUserId(userInfoEntity.getUserId());
        TLMap.setMobile(userInfoEntity.getMobile());
        //这里直接用token进行对比，第二个地方传入的token，而不是数据库中的密码
        return new SimpleAuthenticationInfo(shareUserEntity, tokenEntity.getToken(), this.getClass().getName());
    }

    /**
     * 用户校验方法
     *
     * @param userEntity
     */
    private void verifiedUser(TUserInfoEntity userEntity) {
        //禁用或者被删除
        if (!userEntity.getStatus().equals("0")) {
            try {
                SecurityUtils.getSubject().logout();
            } catch (Exception e) {

            }
            throw new LockedAccountException("账号已被禁用！申诉请联系管理员！");
        }
        if (!userEntity.getUserId().equals(TLMap.getUserId())) {
            try {
                SecurityUtils.getSubject().logout();
            } catch (Exception e) {

            }
            throw new LockedAccountException("账号涉嫌违规或违法操作！");
        }
    }

    /**
     * token校验方法
     *
     * @param tokenEntity
     */
    private void verifiedToken(TUserTokenEntity tokenEntity) {
        if (tokenEntity == null || tokenEntity.getExpireTime().getTime() < System.currentTimeMillis()) {
            try {
                SecurityUtils.getSubject().logout();
            } catch (Exception e) {

            }
            throw new IncorrectCredentialsException("token失效，请重新登录");
        }
        //与当前线程的token不相等
        if (!tokenEntity.getToken().equals(TLMap.getToken())) {
            try {
                SecurityUtils.getSubject().logout();
            } catch (Exception e) {

            }
            throw new IncorrectCredentialsException("token失效，请重新登录");
        }
    }

}
